from .base import BaseHandler
from tornado.websocket import WebSocketHandler
import sys
import time
from celery import Celery
from tornado import gen
import tornado.web
#import tcelery
sys.path.append("..")
from db import sess,Person,AlchemyEncoder,Cate,Role,Role_Node,Node
from pay import AliPay
from func_tool import xTree,get_order_code,jwt_code
import task
import json
import requests
import os
import jwt
import datetime
import pymysql
import redis

#tcelery.setup_nonblocking_producer()


def auth_required():
    def decorator(view_func):
        def _wrapped_view(self,*args, **kwargs):
            token = self.get_argument('token','没有token')
            print(token)
            print('鉴权')
            try:
                de_token = jwt.decode(token,jwt_code,algorithms=['HS256'])
                print('登录了')
            except Exception as e:
                print('没登录')

            #获得当前url
            print(self.request.uri)

            #查看当前用户角色权限
            my_access = sess.query(Node.url,Person.role_id).join(Role,Person.role_id==Role.id).join(Role_Node,Role.id==Role_Node.role_id).join(Node,Role_Node.node_id==Node.id).filter(Person.id==1).all()
            #翻译
            '''
            SELECT node.url AS node_url, person.role_id AS person_role_id 
FROM person INNER JOIN `role` ON person.role_id = `role`.id INNER JOIN role_node ON `role`.id = role_node.role_id INNER JOIN node ON role_node.node_id = node.id 
WHERE person.id = 1
            '''

            for val in my_access:
                print(val.url)



            response = view_func(self, *args, **kwargs)
            return response

        return _wrapped_view

    return decorator


#新浪微博登录地址组合返回（第一步）
class MakeTokenHandler(BaseHandler):

    def get(self,*args,**kwargs):

        encoded_jwt = jwt.encode({'username':'admin'},jwt_code,algorithm='HS256')

        de_code = jwt.decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.5s-L5toU2DrLAjhcjRdEHu7qz39tFpCLw7NokrIY4dw',jwt_code,algorithms=['HS256'])

        
        self.write(json.dumps({'token':str(encoded_jwt,'utf-8'),'decode':de_code}))


#新浪微博登录地址组合返回（第一步）
class SinaFirstHandler(BaseHandler):

    def get(self,*args,**kwargs):

        #微博接口地址
        weibo_auth_url = "https://api.weibo.com/oauth2/authorize"
        #回调网址
        redirect_url = "http://127.0.0.1:8000/md_admin/weibo"
        #应用id
        client_id = "2636039333"
        #组合url
        auth_url = weibo_auth_url + "?client_id={client_id}&redirect_uri={re_url}".format(client_id=client_id,
                                                                                        re_url=redirect_url)
        self.write(auth_url)

#新浪微博回调地址（第二部）
class SinaBackHandler(BaseHandler):

    def get(self,*args,**kwargs):
        #获取回调的code
        code = self.get_argument('code')
        #微博认证地址
        access_token_url = "https://api.weibo.com/oauth2/access_token"
        #参数 向新浪接口发送请求
        re_dict = requests.post(access_token_url,data={
            "client_id": '2636039333',
            "client_secret": "4e2fbdb39432c31dc5c2f90be3afa5ce",
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": "http://127.0.0.1:8000/md_admin/weibo",
        })

        re_dict = re_dict.text
        re_dict = eval(re_dict)
        print(re_dict.get('uid'))

        self.write(re_dict)


#首页
class IndexHandler(BaseHandler):
    #@auth_required()
    def get(self, *args, **kwargs):

        

        #接收参数
        id = self.get_argument('id','未收到')
        print(id)

        #self.finish({'name':'你好'})

        #写入
        #p = Person(name="你好", age=12)
        #sess.add(p)
        #sess.commit()

        #修改
        #p = sess.query(Person).filter(Person.id==1).one()
        p = sess.query(Person).filter().all()
        #p.name = "shuke"
        #sess.commit()


        #返回json 使用类，批量转换
        self.write(json.dumps({"status":0,"msg":"返回成功","user_info":p},cls=AlchemyEncoder,ensure_ascii=False,indent=4))



        #self.write("Hello, world123")
        #self.finish()

    @auth_required()
    def post(self,*args, **kwargs):

        #接收参数
        id = self.get_argument('id','未收到')
        page = self.get_argument('page',1)

        print("id是%s" % id)

        #p = sess.query(Person).filter(Person.id==1).one()
        count = sess.query(Person).count()
        p = sess.query(Person).offset((int(page)-1)*2).limit(2).all()
        #返回json
        self.write(json.dumps({"status":0,"msg":"返回成功","user_info":p,'count':count},cls=AlchemyEncoder,ensure_ascii=False,indent=4))


class MainHandler(BaseHandler):
    async def get(self):
        data_box = {}
        data_box['index_word']='Hello Tornado'
        self.render('../templates/main.html',**data_box)


#无限分类树
class TreeHandler(BaseHandler):
    async def get(self):
        print(self.request.remote_ip)
        cate = sess.query(Cate).filter().all()
        #序列化
        cate_json = json.dumps(cate,cls=AlchemyEncoder,ensure_ascii=False)
        #格式化数据
        mylist= xTree(json.loads(cate_json))
        print(mylist)
        self.render('../templates/tree.html',mylist=json.dumps(mylist,ensure_ascii=False))

#获取ip
class GetIpHandler(BaseHandler):
    async def get(self):
        client_ip = self.request.remote_ip
        print('ip是'+str(client_ip))
        self.write(json.dumps({'ip':client_ip},ensure_ascii=False))


#异步任务
class CeleryHandler(BaseHandler):
    @gen.coroutine
    def get(self):

        yield gen.Task(task.sendmail.apply_async,args=['你好','非常好','164850527@qq.com'])
        print('ok')
        self.write('ok')
        self.finish()


#上传文件
class UploadHandler(BaseHandler):
    async def get(self):
        self.render('../templates/upload.html')

    async def post(self):

        #上传路径
        upload_path = os.path.dirname(os.path.dirname(__file__))+"/static/upload/"

        #接收文件，以对象的形式
        img = self.request.files.get('file', None)
        name = self.get_argument('name','未收到')
        for meta in img:
            filename = meta['filename']
            file_path = upload_path + filename
            with open(file_path, 'wb') as up:
                up.write(meta['body'])

        self.write(json.dumps({'status':'ok'},ensure_ascii=False))

#七牛云token
from qiniu import Auth
class QiNiuHandler(BaseHandler):
    async def get(self):
        q = Auth('E2IZM3koC1GR1DUqJHactmixzdyZZhx0edBKqDsk','GDnMkvRoE_kFhCSuvdqQj0VcNsRDOHzYJJ_bVd0_')
        token = q.upload_token('redinnovation')
        print(token)

        self.write(json.dumps({'uptoken':token},ensure_ascii=False))


#初始化阿里支付对象
def get_ali_object():
    # 沙箱环境地址：https://openhome.alipay.com/platform/appDaily.htm?tab=info
    app_id = "2016092600603658"  #  APPID （沙箱应用）

    # 支付完成后，支付偷偷向这里地址发送一个post请求，识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到，def page2() 接收不到这个请求
    notify_url = "http://localhost:8000/alipayreturn"

    # 支付完成后，跳转的地址。
    return_url = "http://localhost:8000/alipayreturn"

    #秘钥地址
    key_path = os.path.dirname(os.path.dirname(__file__))+"/keys/"
    
    merchant_private_key_path = key_path+"app_private_2048.txt" # 应用私钥
    alipay_public_key_path = key_path+"alipay_public_2048.txt"  # 支付宝公钥

    alipay = AliPay(
        appid=app_id,
        app_notify_url=notify_url,
        return_url=return_url,
        app_private_key_path=merchant_private_key_path,
        alipay_public_key_path=alipay_public_key_path,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥
        debug=True,  # 默认False,
    )
    return alipay


#支付宝支付
class PayPageHandler(BaseHandler):
    async def get(self):
        self.render('../templates/pay.html')

    async def post(self):

        # 根据当前用户的配置，生成URL，并跳转。
        money = self.get_argument('money')

        alipay = get_ali_object()

        # 生成支付的url
        query_params = alipay.direct_pay(
            subject="test",  # 商品简单描述
            out_trade_no="myorder" + str(get_order_code()),  # 用户购买的商品订单号（每次不一样） 20180301073422891
            total_amount=money,  # 交易金额(单位: 元 保留俩位小数)
        )

        pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）

        self.redirect(pay_url)

#支付宝回调
class PayRetrunHandler(BaseHandler):
    async def get(self):
        params = self.request.arguments
        print(params)
        self.write('支付成功')


#websocket 前端页面
class WebHandler(BaseHandler):
    async def get(self):
        self.render('../templates/websocket.html')

#客服系统
class ChatHandler(WebSocketHandler):
 
    users = set()  # 用来存放在线用户的容器
 
    def open(self):
        self.users.add(self)  # 建立连接后添加用户到容器中
        for u in self.users:  # 向已在线用户发送消息
            u.write_message(u"[%s]-[%s]-进入聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
 
    def on_message(self, message):
        for u in self.users:  # 向在线用户广播消息
            u.write_message(u"[%s]-[%s]-说：%s" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))
 
    def on_close(self):
        self.users.remove(self) # 用户关闭连接后从容器中移除用户
        for u in self.users:
            u.write_message(u"[%s]-[%s]-离开聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
    #允许跨域
    def check_origin(self, origin):
        return True


#原生pymysql连接
def my_db():
    conn = pymysql.Connect(host="127.0.0.1", port=3306, user="root",passwd="root",db="hy")
    return conn


#定义过载
def limit_handler():
    """
    return True: 允许; False: 拒绝
    """
    r = redis.Redis(host='localhost', port=6379)

    amount_limit = 3  # 限制数量
    keyname = 'limit'  # redis key name
    incr_amount = 1  # 每次增加数量

    # 判断key是否存在
    if not r.exists(keyname):
        # 为了方便测试，这里设置默认初始值为95
        # setnx可以防止并发时多次设置key
        r.setnx(keyname, 0)

    # 数据插入后再判断是否大于限制数
    if r.incrby(keyname, incr_amount) <= amount_limit:
        return True

    return False

#秒杀系统
#定义秒杀接口
class MiaoShaHandler(BaseHandler):
    async def get(self):
        p = sess.query(Person).filter(Person.id==1).first()
        if limit_handler():
        #if p.age > 0:
            time.sleep(2)
            
            #使用orm
            # p.age = p.age - 1
            # sess.commit()

            #使用orm执行原生sql
            # sess.execute(' update person set age = age - 1 where id = 1')
            # sess.commit()


            #使用原生pymysql
            conn = my_db()
            cursor = conn.cursor()
            cursor.execute(" update person set age = age - 1 where id = 1 ")
            conn.commit()
            cursor.close()
            conn.close()
            self.write('ok')
        else:
            self.write('没有了')


#测试rpc接口
class TestRpcHandler(BaseHandler):
    async def get(self):
        username = self.get_argument('username','没有收到')
        print(username)

        #登录逻辑不写了，而是直接请求rpc的用户认证服务，所有逻辑全在rpc的server端写
        thrift_path = os.path.dirname(os.path.dirname(__file__))+"/pingpong.thrift"
        import thriftpy2
        pingpong_thrift = thriftpy2.load(thrift_path, module_name="pingpong_thrift")
        from thriftpy2.rpc import make_client
        client = make_client(pingpong_thrift.PingPong, '127.0.0.1', 6000)


        print("thrift返回值是:"+client.check_login(username,'123456'))

        self.write('测试rpc')